package cn.xnatural.jpa;

import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.IdentifierGenerator;

import java.io.Serializable;
import java.security.SecureRandom;
import java.util.Calendar;

import static cn.xnatural.jpa.NanoIDGenerator.CS;

/**
 * msid生产器
 */
public class MSIDGenerator implements IdentifierGenerator {
    public static final int length = 21;


    @Override
    public Serializable generate(SharedSessionContractImplementor session, Object entity) throws HibernateException {
        return id(length);
    }


    public static String id(int len) {
        if (len < 8) throw new IllegalArgumentException("Param len must >= 8");
        StringBuilder sb = new StringBuilder();
        Calendar cal = Calendar.getInstance();
        sb.append(base62(cal.get(Calendar.YEAR) % 10 + 10));
        sb.append(base62(cal.get(Calendar.MONTH) + 1));
        sb.append(base62(cal.get(Calendar.DAY_OF_MONTH)));
        sb.append(base62(cal.get(Calendar.HOUR_OF_DAY)));
        sb.append(base62(cal.get(Calendar.MINUTE)));
        sb.append(base62(cal.get(Calendar.SECOND)));
        sb.append(base62(cal.get(Calendar.MILLISECOND)));
        SecureRandom sr = new SecureRandom();
        for (int i = len - 8; i > 0; i--) {
            sb.append(CS[sr.nextInt(CS.length)]);
        }
        return sb.toString();
    }

    static String base62(long num) {
        StringBuilder sb = new StringBuilder();
        while (num > 0) {
            sb.insert(0, CS[(int) (num % CS.length)]);
            num /= CS.length;
        }
        return sb.toString();
    }
}
